Skip to content

feat: init and update keep pharn/.run/ and pharn/.backup/ out of git (0.16.0) - #330

Merged
PrzemekGalarowicz merged 4 commits into
mainfrom
feat/gitignore-run-state
Nov 2, 2026
Merged

PrzemekGalarowicz merged 4 commits into
mainfrom
feat/gitignore-run-state

Conversation

@PrzemekGalarowicz

Copy link
Copy Markdown
Member

Summary

pharn init and pharn update now make sure the project's root .gitignore covers pharn/.run/ (pharn-oss's runtime scratch: stage logs, gate outputs, cost markers) and pharn/.backup/ (pharn's update backups). Release 0.16.0.

Why: installed projects did not ignore pharn/.run/, so run state became tracked. In pharn-oss#408, 55 run-state files were counted as build escapes by reconcile and failed a correct build's verify. pharn-oss 7.2.0 fixed its side; this is the installer's side.

This reverses the documented rule "pharn never edits .gitignore" — for these two lines only. The README and the init/update/add/remove/uninstall docs and the CHANGELOG say so. add, remove and uninstall still never write .gitignore.

Behaviour

  • Create or append. A missing .gitignore is created. An existing one gets only the missing line(s) plus one comment. Its existing bytes are always the unchanged prefix: never reordered or rewritten, CRLF stays CRLF, and a missing final newline gets a separator first.
  • Spellings and negations. An entry counts as present in any of git's equivalent spellings (/pharn/.run, pharn/.run, pharn/.run/*, pharn/.run/**, **/pharn/.run/, a bare .run/), including after a UTF-8 BOM. A negation the user wrote (!pharn/.run/) is respected.
  • Idempotent: a second run writes nothing.
  • Never forced. A symlinked, non-regular or unreadable .gitignore is never written: the run warns and names the lines to add. A failed write is a warning, never a failed install.
  • Same-version update. A missing line re-opens the "Already up to date" return, so existing installs get the lines on their next update (bounded: the next run returns early again).
  • Previews. --dry-run previews the change. init --dry-run --json / update --dry-run --json gain an additive gitignore / plan.gitignore key, present only when .gitignore would change (schemaVersion stays 1).
  • init --yes: .gitignore is not one of its write targets, so init --yes never refuses because of it.
  • Backup notice. Its "not gitignored" advice now prints only when pharn/.backup/ is neither covered nor about to be added.

Tests

  • tests/gitignore.test.ts (61): covers
    • every spelling, a leading space (not counted), negation and BOM;
    • missing, LF, no-final-newline and CRLF files;
    • a second run as a no-op (bytes and mtime);
    • symlink, directory and FIFO refusals;
    • a hard link replaced, never written through;
    • mode kept, and a new file getting the umask mode;
    • an EACCES write returned, not thrown;
    • a real git check-ignore.
  • Cases added to the init/update dry-run (text and JSON), update, backup, atomic-write and unmocked integration suites (init --yes then update --yes, CRLF, idempotent, re-open after a deleted line).
  • Local: npm run check, test:coverage (also with CI=1) and build are green.

🤖 Generated with Claude Code

PrzemekGalarowicz and others added 4 commits November 2, 2026 21:08
…(0.16.0)

pharn init and pharn update now append pharn/.run/ (pharn-oss's runtime
scratch) and pharn/.backup/ (pharn's backups) to the project's root
.gitignore, creating it when absent. An installed project used to track
pharn/.run/, so pharn-oss's reconcile counted PHARN's own run state as
build escapes (pharn-oss #408).

Append-only: the old bytes stay the prefix, only missing entries are
added in the file's own line endings, equivalent spellings and
negations are respected, and a second run writes nothing. A symlinked
or unusable .gitignore is never written; the run warns instead. A
missing entry re-opens update's same-version early return. Dry runs
preview it, and the --json reports gain an additive gitignore key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…re-run-state

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Git strips a leading BOM from .gitignore, so an entry on the first line
of a BOM file is already in force; pharn now reads it the same way
instead of appending a redundant duplicate. Detection only: the file's
bytes are never changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 32e30536-9b30-4d35-9d96-ec47915db332
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

pharn

🛡️ pharn-ci · ✅ Pass

Tip

Pass · Diff coverage of this change is 99.12% against a threshold of 80%; 20 agent setup files found.

Verdict Diff coverage Test integrity Agent setup
✅ Pass 99.12% (threshold 80%) none (block) 20 files

🧪 Diff coverage

99.12% of changed lines covered (112/113, threshold 80%)

Changed files (10)
File Coverage Covered Uncovered lines
src/lib/gitignore.ts 98.85% 86/87 187
src/commands/init.ts 100% 3/3
src/commands/uninstall.ts 100% 2/2
src/commands/update.ts 100% 5/5
src/lib/atomic-write.ts 100% 3/3
src/lib/backup.ts 100% 1/1
src/lib/init-report.ts 100% 2/2
src/lib/update-render.ts 100% 5/5
src/lib/update-report.ts 100% 2/2
src/steps/install-archetype.ts 100% 3/3

🔍 Test integrity

No test-integrity findings (mode: block).

🤖 Agent setup (20 files)

Agent setup: 20 files · claude-code

Agent setup files (20)
Path Kind
.claude/commands/pharn-dev-build.md claude-command
.claude/commands/pharn-dev-eval.md claude-command
.claude/commands/pharn-dev-grill.md claude-command
.claude/commands/pharn-dev-memory-promote.md claude-command
.claude/commands/pharn-dev-plan.md claude-command
.claude/commands/pharn-dev-regress.md claude-command
.claude/commands/pharn-dev-review.md claude-command
.claude/commands/pharn-dev-ship.md claude-command
.claude/commands/pharn-dev-verify.md claude-command
.claude/hooks/enforce-writes-scope.cjs claude-hook
.claude/hooks/enforce-writes-scope.test.cjs claude-hook
.claude/hooks/protect-trusted-paths.cjs claude-hook
.claude/hooks/protect-trusted-paths.test.cjs claude-hook
.claude/hooks/set-writes-scope.cjs claude-hook
.claude/hooks/set-writes-scope.test.cjs claude-hook
.claude/settings.json claude-settings
.claude/skills/pharn-ci-cover claude-skill
.claude/skills/pharn-ci-explain claude-skill
.claude/skills/pharn-ci-install claude-skill
CLAUDE.md claude-md

pharn-ci 0.2.0 · report schema v2 · coverage format lcov

@PrzemekGalarowicz
PrzemekGalarowicz merged commit fff24ad into main Nov 2, 2026
14 checks passed
@PrzemekGalarowicz
PrzemekGalarowicz deleted the feat/gitignore-run-state branch November 2, 2026 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant